package com.dage.salesflow.service;

import com.dage.salesflow.constant.SysConstant;
import com.dage.salesflow.kit.DbKit;
import com.dage.salesflow.kit.Ret;
import com.dage.salesflow.kit.TreeKit;
import com.dage.salesflow.model.Resource;
import com.dage.salesflow.model.vo.Menu;
import com.dage.salesflow.model.vo.TreeNode;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import io.jboot.aop.annotation.Bean;
import io.jboot.service.JbootServiceBase;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Bean
public class ResourceService extends JbootServiceBase<Resource> {
	/**
	 * 权限管理分页查询
	 */
	public List<Resource> list(String name, String code, Integer type) {
		Kv cond = Kv.create();
		if (StrKit.notBlank(name)) {
			cond.set("name like ", "%" + name + "%");
		}
		if (StrKit.notBlank(code)) {
			cond.set("code like ", "%" + code + "%");
		}
		if (type != null && type != -1) {
			cond.set("type=", type);
		}
		List<Resource> list = DAO.template("resource.list", Kv.by("cond", cond)).find();
		Set<Resource> menus = new HashSet<>();
		for (Resource resource : list) {
			getParentMenu(resource.getPid(), menus, list);
		}
		list.addAll(menus);
		return list;
	}

	/**
	 * 获取所有首页
	 */
	public List<Resource> listHome() {
		Kv cond = Kv.create();
		cond.set("type=", Resource.TYPE_HOME);
		return DAO.template("resource.list", Kv.by("cond", cond)).find();
	}

	/**
	 * 递归获取所有父级菜单
	 */
	private void getParentMenu(int pid, Set<Resource> menus, List<Resource> resources) {
		if (pid <= 0) {
			return;
		}
		boolean exist = false;
		//判断原有集合中是否已经存在
		for (Resource resource : resources) {
			if (resource.getId() == pid) {
				exist = true;
				break;
			}
		}
		//不存在时添加父级菜单信息
		if (!exist) {
			Resource menu = new Resource();
			menu.setId(pid);
			if (!menus.contains(menu)) {
				Resource resource = DAO.findById(pid);
				menus.add(resource);
				//递归父级菜单
				getParentMenu(resource.getPid(), menus, resources);
			}
		}
	}

	/**
	 * 获取角色对应的菜单
	 *
	 * @param roleId 角色id
	 * @return
	 */
	public List<Menu> listMenu(int roleId) {
		//递归获取所有菜单（顶级菜单pid=0）
		return listSubMenu(0, roleId);
	}

	/**
	 * 按照角色获取主页菜单和LOGO
	 *
	 * @param roleId
	 * @param type   类型：2.首页3.LOGO
	 * @return
	 */
	public Menu getMenu(int roleId, int type) {
		if (type == Resource.TYPE_LOGO) {
			Menu logoInfo = new Menu(SysConstant.PROJECT_NAME, "/", null);
			logoInfo.setImage("img/icons/logo.png");
			return logoInfo;
		} else {
			Resource resource = DAO.template("resource.getByTypeRole", type, roleId).findFirst();
			return new Menu(resource.getId(), resource.getName(), resource.getUrl(), resource.getIcon());
		}
	}

	/**
	 * Resource转TreeNode
	 *
	 * @param resources 待转换列表
	 * @return
	 */
	private List<TreeNode> resourceToTreeNodes(List<Resource> resources) {
		List<TreeNode> nodes = new ArrayList<>();
		for (Resource resource : resources) {
			TreeNode treeNode = new TreeNode(resource.getId(), resource.getName(), "name");
			if (resource.getPid() == 0) {
				//顶级菜单默认展开
				treeNode.setSpread(true);
			}
			nodes.add(treeNode);
		}
		return nodes;
	}

	private List<Menu> resourceToMenuList(List<Resource> topMenus) {
		List<Menu> menus = new ArrayList<>();
		for (Resource topMenu : topMenus) {
			menus.add(new Menu(topMenu.getId(), topMenu.getName(), topMenu.getUrl(), topMenu.getIcon()));
		}
		return menus;
	}

	/**
	 * 递归获取所有子菜单
	 *
	 * @param pid    父级id
	 * @param roleId 角色id
	 * @return
	 */
	private List<Menu> listSubMenu(int pid, int roleId) {
		List<Menu> menus = resourceToMenuList(DAO.template("resource.listMenuByRole", pid, roleId).find());
		for (Menu menu : menus) {
			menu.setChild(listSubMenu(menu.getId(), roleId));
		}
		return menus;
	}

	/**
	 * 获取角色菜单权限（角色菜单权限分配）
	 *
	 * @param roleId 角色id
	 * @param type   类型
	 * @return
	 */
	public List<TreeNode> listRoleResource(int roleId, int type) {
		//获取角色已有菜单权限
		List<Resource> resources = DAO.template("resource.listRoleResource", type, roleId).find();
		if (type == Resource.TYPE_MENU) {
			return listRoleSubMenu(0, resources);
		} else if (type == Resource.TYPE_PERMISSION) {
			Kv cond = Kv.create();
			cond.set("type=", type);
			//获取所有权限
			List<Resource> list = DAO.template("resource.list", Kv.by("cond", cond)).find();
			Set<Resource> menus = new HashSet<>();
			//递归获取所有权限父节点
			for (Resource resource : list) {
				getParentMenu(resource.getPid(), menus, list);
			}
			list.addAll(menus);
			//构建树形数据
			return listRoleSubResource(0, list, resources);
		} else {
			return null;
		}
	}

	/**
	 * 递归构建权限树形数据
	 *
	 * @param pid       父节点id
	 * @param resources 所有数据
	 * @param rolePerms 角色已有菜单（权限）
	 * @return
	 */
	private List<TreeNode> listRoleSubResource(int pid, List<Resource> resources, List<Resource> rolePerms) {
		List<TreeNode> nodes = new ArrayList<>();
		for (Resource resource : resources) {
			if (resource.getPid() == pid) {
				TreeNode treeNode = new TreeNode(resource.getId(), resource.getName(), "name");
				if (rolePerms.contains(resource)) {
					treeNode.setChecked(true);
				}
				if (pid == 0) {
					//顶级菜单默认展开
					treeNode.setSpread(true);
				}
				treeNode.setChildren(listRoleSubResource(treeNode.getId(), resources, rolePerms));
				nodes.add(treeNode);
			}
		}
		return nodes;
	}

	/**
	 * 递归获取所有角色菜单（角色菜单分配）
	 *
	 * @param pid       父级id
	 * @param rolePerms 角色已有菜单（权限）
	 * @return
	 */
	private List<TreeNode> listRoleSubMenu(int pid, List<Resource> rolePerms) {
		List<TreeNode> menus = resourceToTreeNodes(DAO.template("resource.listMenuByPid", pid).find());
		for (TreeNode menu : menus) {
			menu.setChildren(listRoleSubMenu(menu.getId(), rolePerms));
			if (menu.getChildren() == null || menu.getChildren().isEmpty()) {
				Resource resource = new Resource();
				resource.setId(menu.getId());
				//叶子节点设置选中状态
				menu.setChecked(rolePerms.contains(resource));
			}
		}
		return menus;
	}

	/**
	 * 获取角色拥有的权限
	 *
	 * @param roleId
	 * @return
	 */
	public List<String> listResourceByRole(int roleId) {
		List<Resource> resources = DAO.template("resource.listRoleResource", Resource.TYPE_PERMISSION, roleId).find();
		List<String> list = new ArrayList<>();
		for (Resource resource : resources) {
			list.add(resource.getCode());
		}
		return list;
	}

	/**
	 * 删除
	 *
	 * @param id
	 * @return
	 */
	public Ret del(int id) {
		boolean tx = Db.tx(() -> {
			List<Resource> resources = TreeKit.getChildNodes(id, (Resource) DAO);
			Object[][] paras = new Object[resources.size() + 1][];
			paras[0] = new Object[]{id};
			for (int i = 0; i < resources.size(); i++) {
				paras[i + 1] = new Object[]{resources.get(i).getId()};
			}
			Db.batch("DELETE FROM `t_resource` WHERE id=?", paras, DbKit.DB_BATCH_COUNT);
			Db.batch("DELETE FROM t_role_resource WHERE resource_id=?", paras, DbKit.DB_BATCH_COUNT);
			return true;
		});
		if (tx) {
			return Ret.ok();
		} else {
			return Ret.err("删除失败");
		}
	}

}